package com.chris.config;

import com.chris.filter.TokenAuthenticationFilter;
import com.chris.handler.EntryPointUnauthorizedHandler;
import com.chris.handler.RequestAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;
    @Autowired
    private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler;
    @Autowired
    private RequestAccessDeniedHandler requestAccessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                formLogin()
                .disable() //禁用表单登录
                .apply(jwtAuthenticationSecurityConfig)// 应用登录过滤器的配置，配置分离
                .and()
                .authorizeRequests() //设置url授权
                .antMatchers("/login","/refreshToken")// 将这些url放行
                .permitAll() //代表允许访问
//                .antMatchers("/hello")// 这些url需要ADMIN的角色或者queryHello的权限才能访问
//                .hasAuthority("queryHello")//拥有queryHello的权限
//                .hasRole("ADMIN")//拥有admin角色
                .anyRequest()//其他所有请求
                .authenticated()//必须都要认证
                .and()
                .exceptionHandling()//处理异常情况
                .authenticationEntryPoint(entryPointUnauthorizedHandler)//认证不通过，不允许访问的异常处理器
                .accessDeniedHandler(requestAccessDeniedHandler)//权限不足的异常处理器
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//禁用session，jwt校验不需要session
                .and()
                .addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)//将token校验过滤器配置到过滤器链中，放到UsernamePasswordAuthenticationFilter之前
                .csrf().disable();//关闭csrf
    }

    @Bean
    public TokenAuthenticationFilter authenticationTokenFilter(){
        return new TokenAuthenticationFilter();
    }

    /**
     * 加密算法
     * @return
     */
    @Bean
    public PasswordEncoder getPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
